#include "common/pch.h"

#include <boost/endian/conversion.hpp>

#include <cftf/net/iomgr.h>
#include <cftf/net/tcplistener.h>
#include <cftc/encoding/json.h>
#include <cftf/loger/syslog.h>

#include <iostream>

#include "listener/gglistener.h"
#include "listener/ggsession.h"
#include "metadata/metamgr.h"
#include "cs/msg_descriptor.h"

GGListener::GGListener()
{

}

void GGListener::Init()
{
	int port = mt::MetaMgr::Instance().GetConf()->At("MangosdConf.WorldServerPort")->AsXValue();
	tcplistener_ = std::make_shared<cftf::net::TcpListener>((int)SocketFrom_e::kSkGG, cftf::net::IoMgr::Instance().GetIoContext(0), port, 0xFFFF, 1024 * 64 * 2);
	tcplistener_->RegisterSessionClass<GGSession>();
	tcplistener_->Accept();
}

void GGListener::UnInit()
{
	tcplistener_ = nullptr;
}

bool GGListener::TouchSession(int socket_handle, std::function<void(GGSession*)> cb)
{
	return tcplistener_->TouchSession(socket_handle,
		[&cb](cftf::net::TcpSession* session) {
			cb((GGSession*)session);
		});
}

void GGListener::InternalSendMsg(int socket_handle, unsigned short msgid, std::shared_ptr<cftc::reflect::Object> msg)
{
	cftf::loger::SysLog::Instance().Info(cftc::encoding::Json::Marshal(msg.get()));
	unsigned int msg_byte_size = cs::MsgDescriptor::CalcSerializeMsgByteSize(msg.get());
	if (sizeof(ServerPktHeader) + msg_byte_size > 0xFFFF) {
		abort();
	}
	unsigned char* buf = (unsigned char*)::malloc(sizeof(ServerPktHeader) + msg_byte_size);
	if (buf) {
		ServerPktHeader* head = (ServerPktHeader*)buf;
		head->cmd = msgid;
		head->size = boost::endian::native_to_big((unsigned short)(msg_byte_size + 2));
		unsigned int offset = 0;
		cs::MsgDescriptor::SerializeMsg(msg.get(), buf + sizeof(ServerPktHeader), msg_byte_size, offset);
		if (msg_byte_size != offset) {
			abort();
		}
		{
			std::cout << "STORAGE_SIZE: " << msg_byte_size << "\n";
			for (size_t i = 0; i < msg_byte_size; ++i)
			{
				std::cout << (unsigned int)(buf[i + sizeof(ServerPktHeader)]) << " - ";
			}
		}
		tcplistener_->SendBuf(socket_handle, buf, sizeof(ServerPktHeader) + msg_byte_size);
		::free(buf);
	} else {
		abort();
	}
}
